﻿using System;
using System.Drawing;
using System.Drawing.Imaging;
using System.Web;
using System.Web.SessionState;
using PmfWeb.Core.Utility;
using PmfWeb.Core.Web;

namespace PmfWeb.Core.HttpHandlers
{
    ///<summary>
    /// 验证码处理器(web.config中先注册),使用时: <img id="imgCheckCode" style="cursor:pointer" src="handler.ashx" alt="看不清？点击更换" onclick="this.src=this.src+'?'"/ />
    ///</summary>
    public class VerifyCodeHanlder : IHttpHandler, IRequiresSessionState
    {
        #region IHttpHandler接口成员
        /// <summary>
        /// 处理请求
        /// </summary>
        /// <param name="context"></param>
        public void ProcessRequest(HttpContext context)
        {
            int i = Current.GetInt("i");
            if (i < 4 || i > 6) i = 4;
            this.CreateCheckCodeImage(GenerateCheckCode(i),context);
        }
        /// <summary>
        /// 是否缓存请求
        /// </summary>
        public bool IsReusable
        {
            get { return true;}
        }

        /// <summary>
        /// 生成验证码
        /// </summary>
        /// <returns></returns>
        private string GenerateCheckCode(int ilen)
        {
            int number;
            char code;
            string checkCode = "";
            if (ilen < 4 || ilen > 8) ilen = 4;
            System.Random random = new Random();
            for (int i = 0; i < ilen; i++)
            {
                number = random.Next();
                if (number % 2 == 0)
                    code = (char)('0' + (char)(number % 10));
                else
                    code = (char)('0' + (char)(number % 10));
                checkCode += code.ToString();
            }
            HttpContext.Current.Response.Cookies.Add(new HttpCookie("CheckCode", DESncrypt.GetMD5(checkCode.ToLower())));

            //将生成的随机数保存到session中
            HttpContext.Current.Session["Num"] = DESncrypt.MakeMD5(checkCode.ToLower());
            return checkCode;
        }

        /// <summary>
        /// 生成验证码图片
        /// </summary>
        /// <param name="checkCode">验证码</param>
        /// <param name="context">当前上下文</param>
        private void CreateCheckCodeImage(string checkCode, HttpContext context)
        {
            if (checkCode == null || checkCode.Trim() == System.String.Empty)
                return;

            Bitmap image = new Bitmap((int)Math.Ceiling((checkCode.Length * 12.5)), 22);
            Graphics g = Graphics.FromImage(image);

            try
            {
                //生成随机生成器 
                Random random = new Random();

                //清空图片背景色 
                g.Clear(Color.White);

                //画图片的背景噪音线 
                for (int i = 0; i < 25; i++)
                {
                    int x1 = random.Next(image.Width);
                    int x2 = random.Next(image.Width);
                    int y1 = random.Next(image.Height);
                    int y2 = random.Next(image.Height);

                    g.DrawLine(new Pen(Color.Silver), x1, y1, x2, y2);
                }

                Font font = new Font("Arial", 12, (FontStyle.Bold | FontStyle.Italic));
                System.Drawing.Drawing2D.LinearGradientBrush brush = new System.Drawing.Drawing2D.LinearGradientBrush(new Rectangle(0, 0, image.Width, image.Height), Color.Blue, Color.DarkRed, 1.2f, true);
                g.DrawString(checkCode, font, brush, 2, 2);

                //画图片的前景噪音点 
                for (int i = 0; i < 100; i++)
                {
                    int x = random.Next(image.Width);
                    int y = random.Next(image.Height);

                    image.SetPixel(x, y, Color.FromArgb(random.Next()));
                }

                //画图片的边框线 
                g.DrawRectangle(new Pen(Color.Silver), 0, 0, image.Width - 2, image.Height - 1);

                System.IO.MemoryStream ms = new System.IO.MemoryStream();
                image.Save(ms, ImageFormat.Gif);
                context.Response.ClearContent();
                context.Response.ContentType = "image/Gif";
                context.Response.BinaryWrite(ms.ToArray());
            }
            finally
            {
                g.Dispose();
                image.Dispose();
            }
        }

        /// <summary>
        /// 显示验证码
        /// </summary>
        /// <param name="seed">随机数辅助种子</param>
        /// <param name="strLen">验证码字符长度</param>
        /// <param name="fontSize">字体大小</param>
        /// <param name="clrFont">字体颜色</param>
        /// <param name="clrBg">背景颜色</param>
        private void ShowValidationCode(ref int seed, int strLen, int fontSize, Color clrFont, Color clrBg)
        {
            int tmpSeed;
            unchecked
            {
                tmpSeed = (int)(seed * DateTime.Now.Ticks);
                ++seed;
            }
            Random rnd = new Random(tmpSeed);

            string text = GenerateCheckCode(strLen);
            int height = fontSize * 2;
            // 因为字体旋转后每个字体所占宽度会所有加大，所以要加一点补偿宽度
            int width = fontSize * text.Length + fontSize / (text.Length - 2);
            Bitmap bmp = new Bitmap(width, height);

            Graphics graphics = Graphics.FromImage(bmp);
            Font font = new Font("Courier New", fontSize, FontStyle.Bold);
            Brush brush = new SolidBrush(clrFont);
            Brush brushBg = new SolidBrush(clrBg);
            graphics.FillRectangle(brushBg, 0, 0, width, height);
            Bitmap tmpBmp = new Bitmap(height, height);
            Graphics tmpGph = null;
            int degree = 40;
            Point tmpPoint = new Point();
            for (int i = 0; i < text.Length; i++)
            {
                tmpBmp = new Bitmap(height, height);
                tmpGph = Graphics.FromImage(tmpBmp);
               // tmpGph.TextRenderingHint = System.Drawing.Text.TextRenderingHint.SingleBitPerPixelGridFit;
               // 不填充底色，文字 ClearType 效果不见了，why?!
               // tmpGph.FillRectangle(brushBg, 0, 0, tmpBmp.Width, tmpBmp.Height);
                degree = rnd.Next(20, 51); // [20, 50]随机角度
                if (rnd.Next(0, 2) == 0)
                {
                    tmpPoint.X = 12; // 调整文本坐标以适应旋转后的图象
                    tmpPoint.Y = -6;
                }
                else
                {
                    degree = ~degree + 1; // 逆时针旋转
                    tmpPoint.X = -10;
                    tmpPoint.Y = 6;
                }

                tmpGph.RotateTransform(degree);
                tmpGph.DrawString(text[i].ToString(), font, brush, tmpPoint);
                graphics.DrawImage(tmpBmp, i * fontSize, 0); // 拼接图象
            }
            
            //输出图象
            System.IO.MemoryStream memoryStream = new System.IO.MemoryStream();
            bmp.Save(memoryStream, System.Drawing.Imaging.ImageFormat.Gif);
            HttpContext.Current.Response.Cache.SetCacheability(HttpCacheability.NoCache);
            HttpContext.Current.Response.ClearContent();
            HttpContext.Current.Response.ContentType = "image/gif";
            HttpContext.Current.Response.BinaryWrite(memoryStream.ToArray());
            HttpContext.Current.Response.End();

            //释放资源
            font.Dispose();
            brush.Dispose();
            brushBg.Dispose();
            if (tmpGph != null) tmpGph.Dispose();
            tmpBmp.Dispose();
            graphics.Dispose();
            bmp.Dispose();
            memoryStream.Dispose();
        }
        #endregion
    }
}
